﻿/*
** Name:xl
** version:1.0
** author:Javin
** E-mail:okwxj@qq.com
** description:该库主要弥补Jquery对原声生JS核心扩展很弱的缺陷
*/
var xl = $xl = function(o){
	return new xl.__init(o);
};
String.prototype.toXL = function(){ return new xl.__init(this);};
Object.prototype.toXL = function(){ return new xl.__init(this);};
//Object.prototype.to$ = function(){ return new xl.$.__init(this);};
Array.prototype.toXL = function(){ return new xl.__init(this);};
Function.prototype.toXL = function(){ return new xl.__init(this);};

xl.about = {version:'1.0'};

xl.__init = function(o){
	this.mem = o;
}
//JS核心扩展(数组，对象，字符串等)

xl.__init.prototype = {
	//通用方法
	get: function(){
		return this.mem;
	},
	isString: function(){
		return this.mem.constructor == String;
	},
	isObject: function(){
		return this.mem.constructor == Object;
	},
	isArray: function(){
		return this.mem.constructor == Array;
	},
	isFunction: function(){
		return this.mem.constructor == Function;
	},
	isEmpty: function(){
		return (this.mem === undefined || this.mem === null || !xl(this.mem).trim());
	},
	isNumber: function(){
		return (!isNaN(this.mem) && this.mem != undefined && this.mem != null);
	},
	isEmpty: function(){
		if(xl(this.mem).isObject()){
			var temp = 0;
			for(var i in this.mem){
				++ temp;
				if(temp > 0) return false;
			}
			return true;
		}
		if(xl(this.mem).isArray() || xl(this.mem).isString()) return (this.mem.length > 0) ? false : true;
	},
	include: function(o){
		if(xl(this.mem).isObject()){
			for(var key in this.mem){
				if(o === key) return true;
			}
		}
		if(xl(this.mem).isArray() || xl(this.mem).isString()){
			for(var i = 0, l = this.mem.length; i < l; i++){
				if(this.mem[i] === o) return true;
			}
		}
		return false;
	},
	first: function(){
		if(xl(this.mem).isString()) return xl(this.mem.substring(0,1));
		if(xl(this.mem).isArray()) return xl(this.mem[0]);
		return this;
	},
	empty: function(){
		if(xl(this.mem).isObject()) this.mem = {};
		if(xl(this.mem).isArray()) this.mem = [];
		if(xl(this.mem).isString()) this.mem = '';
	},
	//字符串方法
	trim: function(){
		if(!xl(this.mem).isString()) return this;
		this.mem = this.mem.replace(/(^\s*)|(\s*$)/gi,'');
		return this;
	},
	lTrim: function(){
		if(!xl(this.mem).isString()) return this;
		this.mem = this.mem.replace(/^\s*/gi,'');
		return this;
	},
	rTrim: function(){
		if(!xl(this.mem).isString()) return this;
		this.mem = this.mem.replace(/\s*$/gi,'');
		return this;
	},
	bytes: function(){
		return this.mem.replace(/[^\x00-\xff]/g, "  ").length;
	},
	//对象方法
	extend: function(o){
		if(!xl(this.mem).isObject() || !xl(this.mem).isObject()) return this;
		for(var i in o){
			this.mem[i] = o[i];
		}
		return this;
	},
	
	//事件方法
	target: function(){
		var e = window.event || this.mem;
		return xl.$(e.srcElement || e.target) || null;
	}
};
//--------------------------------------------------------------选择器-----------------------------------------------------
xl.$ = function(selector){
	return new xl.$.init(selector);
};

xl.$.fn = xl.$.prototype = {
	_this: this,
	nodes: [],
	init: function(selector){
		if(xl(selector).isString()){
			try{
				this.nodes = Array.prototype.slice.call(document.querySelectorAll(selector));
			}catch(e){
				var _a = selector.split(',');
				
				for(var m = 0,l = _a.length; m < l; m++){
					var _ca = _a[m].split(' ');
					
					for(var n = 0,l1 = _ca.length; n < l1; n++){
						this.selector(_ca[n]);
					}
				}
			}
		}else{
			this.nodes.push(selector);
		}
		Array.prototype.push.apply(this,this.nodes);
		return this;
		return this.nodes;
	},
	//选择器核心
	selector: function(s){
			
		//根据id获取node
		if(xl(s).trim().first().get() === '#'){
			this.nodes.push(document.getElementById(s.replace('#','')) || null);
		}
		//根据class获取node
		if(xl(s).trim().first().get() === '.'){
			if(xl(this.nodes).isEmpty()){
				var node = document.getElementsByTagName('*');
				
				for(var i = 0,l = node.length; i < l; i++){
					if(node[i].className == s.replace('.','')){
						this.nodes.push(node[i]);
					}
				}
			}else{
				var nodes = this.nodes;
				this.nodes = [];
				
				for(var i = 0,l = nodes.length; i < l; i++){
					var childs = nodes[i].getElementsByTagName('*');
					for(var j = 0, l1 = childs.length; j < l1; j++){
						if(childs[j].className == s.replace('.','')){
							this.nodes.push(childs[j]);
						}
					}
				}
			}
		}
		//根据tagname获取node
		if(xl(s).trim().first().get() !== '.' && xl(s).trim().first().get() !== '#'){
			var pos = s.indexOf('.');
			var tagname = pos > 0 ? s.substring(0,pos) : s;
			var cls = pos > 0 ? s.substring(pos + 1) : '';
				
			if(xl(this.nodes).isEmpty()){
				var node = document.getElementsByTagName(tagname);
				
				if(cls === ''){
					for(var i = 0,l = node.length; i < l; i++){
						this.nodes.push(node[i]);
					}
				}else{
					for(var i = 0,l = node.length; i < l; i++){
						if(node[i].className == cls){
							this.nodes.push(node[i]);
						}
					}
				}
				
			}else{
				var nodes = this.nodes;
				this.nodes = [];
				
				for(var i = 0,l = nodes.length; i < l; i++){
					var childs = nodes[i].getElementsByTagName(tagname);
					
					if(cls === ''){
						for(var j = 0,l1 = childs.length; j < l1; j++){
							this.nodes.push(childs[j]);
						}
					}else{
						for(var j = 0,l1 = childs.length; j < l1; j++){
							if(childs[j].className == cls){
								this.nodes.push(childs[j]);
							}
						}
					}
				}
			}
		}
	},
	get: function(){
		return this.nodes;
	},
	html: function(){
		if(this.nodes[0]) return this.nodes[0].innerHTML;
		return '';
	},
	click: function(fn){
		for(var index = 0,len = this.nodes.length; index < len; index++){
			xl.addEventListener(this.nodes[index],'click',fn);
		}
	}
};

xl.$.prototype = {
	
	
};

//node方法

xl.Class = function(){
	
};

//小功能方法

/** 
 * @fileoverview  xunlei JavaScript Library
 * @author Brice Li (brice_li@hotmail.com QQ: 19130696 RTX: lixin)
 * @version 0.5 
 * @date 2009-08-05
 */
//common tool
/**
 * 同document.getElementByID()
 * @namespace 常用工具
 * @param {String} e page element id
 * @return page element
 */
/*var xl = function(e){
	return document.getElementById(e);
}*/
/**
 * 返回当前URL上的变量 "http://a.xunlei.com/?name1=value1&name2=value2&...."
 * @param {String} n 变量名
 * @return 变量值
 */
 
xl.addEventListener = function(target,e,fn){
	if(target.addEventListener){
		target.addEventListener(e,fn,false);
	}else if(target.attachEvent){
		target.attachEvent('on'+e,fn);
	} else{
		target['on'+e] = fn;
	}
};
 
xl.$A = function(a){
	var _a = [];
	if(a.length > 0){
		for(var i = 0,l = a.length; i < l; i++){
			_a.push(a[i]);
		}
	}
	return _a;
}

xl.P = function(n){
	var hrefstr, pos, parastr, para, tempstr;
	hrefstr = window.location.href;
	pos = hrefstr.indexOf("?");
	parastr = hrefstr.substring(pos + 1);
	para = parastr.split("&");
	tempstr = "";
	for (i = 0; i < para.length; i++) {
		tempstr = para[i];
		pos = tempstr.indexOf("=");
		if (tempstr.substring(0, pos) == n) {
			return tempstr.substring(pos + 1);
		}
	}
	return null;
}
//cookie operation
/**
 * 添加或覆盖cookie
 * @param {String} name cookie变量名
 * @param {String} value cookie变量值
 * @param {Object} p cookie的其他附加参数 格式如下（没有则默认为null）<br/>
 * 	{"expires": [cookie存在的时间，可以是"session" "hour" "day" "week" "year" "forever" 或 毫秒数或 Date对象],<br/>
 * 		"path":null,<br/>
 * 		"domain":null,<br/>
 * 		"secure":null}<br/>
 */
xl.setCookie = function(name,value,p){
	  var sCookie = name + '=' + encodeURIComponent(value);
	  if(p){
	  	if(p.expires){
		  	if(p.expires!="session"){
				var etime = new Date();
				if(p.expires instanceof Date){ etime = p.expires}
				else if(!isNaN(p.expires)){etime.setTime(etime.getTime() + p.expires)}
				else if(p.expires=="hour"){etime.setHours(etime.getHours() + 1);}
				else if(p.expires=="day"){etime.setDate(etime.getDate() + 1)}
				else if(p.expires=="week"){etime.setDate(etime.getDate() + 7);}
				else if(p.expires=="year"){etime.setFullYear(etime.getFullYear() + 1);}
				else if(p.expires=="forever"){etime.setFullYear(etime.getFullYear() + 120);}//够了。。。
				else{etime = p.expires}
				sCookie += "; expires=" + etime.toGMTString();
			}
		  }
		  if(p.path){
		  	sCookie += "; path=" + p.path;
		  }else{
			sCookie += "; path=/";  
		  }
		  if(p.domain){
		  	sCookie += "; domain=" + p.domain;
		  }else{
			sCookie += "; domain=.xunlei.com";
		  }
		  if(p.secure){
		  	sCookie += "; secure=" + p.secure;
		  }
	  }
	  document.cookie=sCookie;
}
/**
 * 删除cookie
 * @param {String} name cookie变量名
 */
xl.delCookie = function(name){
	xl.setCookie(name,'',{"expires":new Date(0)});
}
/**
 * 得到cookie值
 * @param {String} name cookie变量名
 * @return cookie 变量值
 */
xl.getCookie = function(name){
	var sRE = "(?:; )?" + name + "=([^;]*);?";
	var oRE = new RegExp(sRE);
	if(oRE.test(document.cookie)){
		return decodeURIComponent(RegExp["$1"]);
	}else{
		return null;
	}
}
//json operation
/**
 * @namespace json工具需要使用到的常量和方法
 */
xl.json = {};
/**
 * @private 
 * @param {Object} n
 */
xl.json._toIntegersAtLease = function(n){
	return n < 10 ? '0' + n : n;
}
/**
 * @private 
 */
xl.json._escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;
/**
 * @private 
 */
xl.json._meta = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };
/**
 * @private 
 * @param {String} n
 */
xl.json._quoteString = function(string){
	if (xl.json._escapeable.test(string)){
    	return '"' + string.replace(xl.json._escapeable, function (a){
                var c = xl.json._meta[a];
                if (typeof c === 'string') {
                    return c;
                }
                c = a.charCodeAt();
                return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
            }) + '"';
        }
        return '"' + string + '"';
}
/**
 * 把一个JSON对象转化成字符串<br/>
 * 和jquery得JSON插件完全相同
 * @param {Object} o json对象
 * @param {Object} compact 可以不输入
 * @returns {String} json字符串
 */
xl.toJSON = function(o, compact){
    var type = typeof(o);
    
    if (type == "undefined") 
        return "undefined";
    else 
        if (type == "number" || type == "boolean") 
            return o + "";
        else 
            if (o === null) 
                return "null";
	if (type == "object" && o instanceof Date){
		return o.getUTCFullYear() + '-' +
             xl.json._toIntegersAtLease(o.getUTCMonth()) + '-' +
             xl.json._toIntegersAtLease(o.getUTCDate());
	}
	// Is it a string?
    if (type == "string") {
        return xl.json._quoteString(o);
    }
    
    // Does it have a .toJSON function?
    if (type == "object" && typeof o.toJSON == "function") 
        return o.toJSON(compact);
		
    // Is it an array?
    if (type != "function" && typeof(o.length) == "number") {
        var ret = [];
        for (var i = 0; i < o.length; i++) {
            ret.push(xl.toJSON(o[i], compact));
        }
        if (compact) 
            return "[" + ret.join(",") + "]";
        else 
            return "[" + ret.join(", ") + "]";
    }
    
    // If it's a function, we have to warn somebody!
    if (type == "function") {
        throw new TypeError("Unable to convert object of type 'function' to json.");
    }
    
    // It's probably an object, then.
    var ret = [];
    for (var k in o) {
        var name;
        type = typeof(k);
        
        if (type == "number") 
            name = '"' + k + '"';
        else 
            if (type == "string") 
                name = xl.json._quoteString(k);
            else 
                continue; //skip non-string or number keys
        var val = xl.toJSON(o[k], compact);
        if (typeof(val) != "string") {
            // skip non-serializable values
            continue;
        }
        
        if (compact) 
            ret.push(name + ":" + val);
        else 
            ret.push(name + ": " + val);
    }
    return "{" + ret.join(", ") + "}";
}
/**
 * 等同于eval([json string])把json string转换为json 对象
 * @param {String} data json String
 * @returns {Object} json object
 */
xl.evalJSON = function(data){
	return eval(("(" + data + ")"));
}
/**
 * string.trim方法
 * @param {String} text
 * @returns {String}
 */
xl.trim = function(text){
	return (text || "").replace( /^\s+|\s+$/g, "" );
}
/**
 * 序列化json map 把{"a":1,"b":2} 转化为 a=1&b=2的形式 ，值默认都会被encode
 * @param {Object} params json map like {"a":1,"b":2}
 * @returns {String} 序列化的结果
 */
xl.param = function(params){
	var p = "";
	for(var pp in params)
		p += "&" + pp + "=" + encodeURIComponent(params[pp]);
	return p.length > 1 ? p.slice(1) : p ;
}
/**
 * 获取url上的参数
 * @param {String} params 字符串
 * @returns {String}
 */
xl.getURLParam = function(params){
	var arr = decodeURI(location.search.substring(1)).split('&');
	for(var i = 0, len = arr.length; i < len; i++){
		if(arr[i].substring(0,arr[i].indexOf('=')) == params){
			return arr[i].substring(arr[i].indexOf('=')+1);
		}
	}
}
/**
 * 把形如 "YYYY-MM-DD" 的字符串解析为Date对象
 * @param {String} str 字符串
 * @param {String} format 默认"yyyy-mm-dd"
 * @returns {Date}
 */
xl.parseDate = function(str,format){
	var vals = str.split("-");
	var td = new Date();
	td.setFullYear(vals[0]);
	if(vals[1].charAt(0)=='0') vals[1] = vals[1].charAt(1);
	td.setMonth(vals[1]-1);
	if(vals[2].charAt(0)=='0') vals[2] = vals[2].charAt(1);
	td.setDate(vals[2]);
	td.setHours(0);
	td.setMinutes(0);
	td.setMilliseconds(0);
	return td;
}
/**
 * 请求一段javascript脚本并执行，通过此方法可以实现跨域夸端口通信<br/>
 * 请求的javascript脚本格式如下: var [变量名] = [数据];
 * @param {String} url 服务器地址
 * @param {Object} params json map形式的参数表
 * @param {Object} callback 请求成功后回调方法，会传入请求的变量
 * @param {String} rtnName 服务器返回的变量名，默认为“scriptDataRtn” 这个依赖服务器配合，请求时会给服务器传入参数rtnName=[rtnName]
 */
xl.getScript = function(url,params,callback,rtnName){
	scriptBlock = document.createElement("script");
	scriptBlock.type = "text/javascript";
	var name = rtnName;
	if(!name||xl.trim(name)==""){
		name = "scriptDataRtn";
	}
	var surl = "?rtnName=" + name;
	if(params)
		surl += "&" + xl.param(params);
	scriptBlock.src = url + surl;
	if(window.navigator.userAgent.indexOf("MSIE")>=1){
		scriptBlock.onreadystatechange = function(){
			if("loaded" == scriptBlock.readyState || "complete" == scriptBlock.readyState){
				if(callback)
					callback(eval(name));
			}
		}
	}else{
		scriptBlock.onload = function(){
			if(callback)
				callback(eval(name)); 
		}
	}
	document.getElementsByTagName("head")[0].appendChild(scriptBlock);
}
/**
 * 加载图片，用来实现图片预加载
 * @param {String} url 图片路径
 * @param {Function} callback 成功后回调，传入第一个参数为预加载的图片对象
 */
xl.loadImage = function(url, callback) {
    var img = new Image(); //创建一个Image对象，实现图片的预下载
    img.src = url;
	if(callback && typeof(callback) == 'function'){
		if (img.complete) { // 如果图片已经存在于浏览器缓存，直接调用回调函数
			callback(img);
			return; // 直接返回，不用再处理onload事件
		}
		img.onload = function () { //图片下载完毕时异步调用callback函数。
			callback(img);//将回调函数的this替换为Image对象
		};
	}
	
};

//util class tools
/**
 * @class 
 * @constructor 
 * @param {String} str 可以接受一个字符串作为参数
 */
xl.StringBuffer = function(str){
	this._string = [];
	if(str) this._string.push(str); 
}
xl.StringBuffer.prototype = {
	/**
	 * 为buffer添加字符串
	 * @function  
	 * @param {String} str
	 * @returns {String} this
	 */
	append : function(str){
		this._string.push(str);
		return this;
	},
	/**
	 * @function
	 * @returns {String} 
	 */
	toString : function(){
		return this._string.join("");
	}
}